home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
MSDOS
/
(m)aak
/
UNCRUNCH.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1987-06-20
|
8KB
|
153 lines
procedure UNCRUNCH (var Addr1,Addr2; BlkLen:Integer);
{This is the flash display routine used to display crunched TheDraw image
files. It uses a custom protocol for reproducing a image with any
possible color combinations. The control codes below #32 are reserved
for this function. The following data structure shows the format of a
sequence. Not all operations use the optional bytes <x> or <y>..
Data Structure: <current byte>[<x>[<y>]]
0..15 = New Foreground Color
16..23 = New Background Color
24 = Go down to next line, return to same horizontal position as when
routine was started (akin to a c/r).
25 = Displays <x> number of spaces.
26 = Displays <x> number of <y>. Also used to display ANY characters
below #32. This function is the only way to do this although it
uses three bytes. Otherwise the code would be interpreted as
another command.
----------------------------------------------------------------------------
To use this routine you call the procedure with the ImageData as the
first parameter, the display address as the second parameter, and the
length of the ImageData as the third parameter.
Assume we have a ImageData file of a 40 characters by 10 lines block. Also
the following defintions. ie:
type ScreenType = array [0..3999] of Byte;
var ScreenAddr : ScreenType absolute $B800:$0000;
const ImageData : array [1..467] of Byte =
(...list of image bytes here...);
begin
UnCrunch (ImageData,ScreenAddr[ (34*2) + (5*160) -162],467);
end;
SCREENADDR is a variable mapped to the same location as the physical video
addresses (using Turbo's absolute addressing). The fairly complex array
address in the call tells UnCrunch where to start displaying the ImageData
40 character by 10 line block. The 34*2 indicates the horizontal position
number 34 with the 5*160 indicating line number 5. This is similar to a
Turbo GOTOXY (34,5) statement, except it works for UnCrunch instead.
The value of 467 used in the call is the length of the array as indicated
in the CONST statement.
UnCrunch remembers the horizontal (X) starting position when it goes down
to the next line. This allows you to display the ImageData block correctly
at any position on the screen. ie:
+-------------------------------------------------+
| |
| | <- Pretend this
| | is the video
| ┌─────────────────────┐ | display.
| │█████████████████████│ |
| │█████████████████████│ |
| │██ ImageData block ██│ |
| │█████████████████████│ |
| │█████████████████████│ |
| │█████████████████████│ |
| └─────────────────────┘ |
| |
| |
| |
+-------------------------------------------------+
The ImageData block could just as well have been display in the upper-left
corner of the screen with:
UNCRUNCH (ImageData,ScreenAddr[ (1*2) + (1*160) -162],467);
Notice the array address changed to the equivilant of GOTOXY (1,1);
To display the block in the lower-right corner you would use:
UNCRUNCH (ImageData,ScreenAddr[ (40*2) + (15*160) -162],467);
The block is 40 characters wide by 10 lines deep. Therefore to display
such a large block, we must display the block at GOTOXY (40,15);
Obviously I have been attempting to describe this procedure by use of
examples. This is done because I feel it is the easiest and clearest way
of explaining this procedure. It was designed to be as simple as possible,
however for some people the best way to learn it is to experiment. Try
creating a program using the above example information. Use TheDraw to
make a 40 by 10 block (or any size) to experiment with. Good luck. If
you can devise a better way of explaining this, please share your labors
with me. Others will surely benifit. Thanks!
}
begin
inline (
$1E/ { PUSH DS}
$C5/$B6/Addr1/ { LDS SI,[BP+Addr1] ;Source Address}
$C4/$BE/Addr2/ { LES DI,[BP+Addr2] ;Destination Addr}
$8B/$8E/BlkLen/ { MOV CX,[BP+BlkLen] ;Length of block}
$8B/$D7/ { MOV DX,DI ;Save X coord for later.}
$B4/$00/ { MOV AH,0 ;Current attributes.}
$AC/ {LOOPA: LODSB ;Get next character.}
$3C/$10/ { CMP AL,16 ;If less than 16,}
$73/$07/ { JNC Short BackG ;then change the}
$80/$E4/$F0/ { AND AH,0F0H ;foreground color.}
$0A/$E0/ { OR AH,AL}
$EB/$44/ { JMP Short Next}
$3C/$18/ {BackG: CMP AL,24 ;If less than 24,}
$74/$13/ { JZ Short NextL ;then change the}
$73/$19/ { JNC Short Multi ;background color.}
$2C/$10/ { SUB AL,16}
$02/$C0/ { ADD AL,AL}
$02/$C0/ { ADD AL,AL}
$02/$C0/ { ADD AL,AL}
$02/$C0/ { ADD AL,AL}
$80/$E4/$0F/ { AND AH,0FH}
$0A/$E0/ { OR AH,AL}
$EB/$2D/ { JMP Short Next}
$81/$C2/$A0/$00/ {NextL: ADD DX,160 ;If equal to 24,}
$8B/$FA/ { MOV DI,DX ;then jump down to}
$EB/$25/ { JMP Short Next ;the next line.}
$3C/$1A/ {Multi: CMP AL,26 ;If equal to 26,}
$75/$0B/ { JNZ Space ;then using the}
$AC/ { LODSB ;following two codes}
$49/ { DEC CX ;Adjust main counter.}
$51/ { PUSH CX ;display as many of}
$32/$ED/ { XOR CH,CH ;whatever the user}
$8A/$C8/ { MOV CL,AL ;wants.}
$AC/ { LODSB ;Get character.}
$EB/$0D/$90/ { JMP Start ;Use below loop.}
$3C/$19/ {Space: CMP AL,25 ;If equal to 25,}
$75/$11/ { JNZ Short Lettr ;then using the}
$AC/ { LODSB ;following code as}
$51/ { PUSH CX ;a count, output}
$32/$ED/ { XOR CH,CH ;said number of}
$8A/$C8/ { MOV CL,AL ;spaces.}
$B0/$20/ { MOV AL,32}
$0B/$C9/ {Start: OR CX,CX ;Abort if already}
$74/$03/ { JZ Stop ;at zilch.}
$AB/ {LOOPB: STOSW}
$E2/$FD/ { LOOP LOOPB}
$59/ {Stop: POP CX}
$49/ { DEC CX ;Adjust main counter.}
$AB/ {Lettr: STOSW ;Save screen letter.}
$0B/$C9/ {Next: OR CX,CX ;Get next, unless}
$74/$02/ { JZ Done ;CX has already}
$E2/$AA/ { LOOP LOOPA ;gone to zero.}
$1F); {Done: POP DS}
end; {UNCRUNCH}